﻿// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Media;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Kinect;
using Coding4Fun.Kinect.Wpf;
using Coding4Fun.Kinect;
using System.IO;
using System.Threading;
using System.Runtime.InteropServices;
using System.Windows.Input.StylusPlugIns;
using System.Windows.Ink;
using Microsoft.Xna.Framework;
using System.ComponentModel;
using InkAnalysis;
using Coding4Fun.Kinect.Wpf.Controls;
using System.Windows.Media.Media3D;

namespace Oprah
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class Sky : Window
    {

        [DllImport("user32")]

        
        public static extern int SetCursorPos(int x, int y);
        DepthImagePoint rightDepthPoint;

        private const int MOUSEEVENTF_MOVE = 0x0001;
        private const int MOUSEEVENTF_LEFTDOWN = 0x0002;
        private const int MOUSEEVENTF_LEFTUP = 0x0004;
        private const int MOUSEEVENTF_RIGHTDOWN = 0x0008;

        [DllImport("user32.dll",
            CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]

        public static extern void mouse_event(int dwflags, int dx, int dy, int cButtons, int dwExtraInfo);
        //public static CustomPen pen = null;
        private String wording = "";

        public Sky(string words)
        {
            InitializeComponent();
            wording = "sun";
            SetImage("sun");
            audioPlayer.Source = new Uri("C:/Users/student/Documents/Visual Studio 2010/Projects/Hitler/Audio/WriteTheWord.mp3", UriKind.RelativeOrAbsolute);
            audioPlayer.LoadedBehavior = MediaState.Play;
            audioPlayer.UnloadedBehavior = MediaState.Close;

            //Window2Panel panel = new Window2Panel();
            //this.ink.Children.Add(panel);
            //panel.Background = new SolidColorBrush(Colors.Transparent);

            ink.UseCustomCursor = true;
            ink.DefaultDrawingAttributes.FitToCurve = true;
            ink.DefaultDrawingAttributes.Width = 10;
            ink.DefaultDrawingAttributes.Height = 10;
            ink.DefaultDrawingAttributes.Color = Colors.Blue;
            image2.Source = new BitmapImage(new Uri("/images/chalk.png", UriKind.RelativeOrAbsolute));
            this.Cursor = CustomCursor.CreateCursor(image2, 5, 5);
            kinectSensorChooser1.KinectSensorChanged += new DependencyPropertyChangedEventHandler(kinectSensorChooser1_KinectSensorChanged);
        }

        private void SetImage(string word)
        {
            //string path = "";
            foreach (WB wb in WB.wordbank)
            {
                if (word == wb.word)
                {
                    imgPicture.Visibility = Visibility.Visible;
                    imgPicture.Source = new BitmapImage(new Uri(wb.path, UriKind.RelativeOrAbsolute));
                    break;
                }
            }
        }

        InkAnalyzer m_analyzer;
        void onLoaded(object sender, RoutedEventArgs e)
        {
            

            m_analyzer = new InkAnalyzer();
            m_analyzer.AnalysisModes = AnalysisModes.AutomaticReconciliationEnabled;
            m_analyzer.ResultsUpdated += new ResultsUpdatedEventHandler(m_analyzer_ResultsUpdated);
        }

        //void onStrokeErasing(object sender, InkCanvasStrokeErasingEventArgs e)
        //{
        //    m_analyzer.RemoveStroke(e.Stroke);
        //}

        void onStrokeCollected(object sender, InkCanvasStrokeCollectedEventArgs e)
        {
            m_analyzer.AddStroke(e.Stroke);
            
            m_analyzer.AnalysisModes = AnalysisModes.AutomaticReconciliationEnabled;
        }

        void m_analyzer_ResultsUpdated(object sender, ResultsUpdatedEventArgs e)
        {
            if (e.Status.Successful)
            {
                ContextNodeCollection nodes = ((InkAnalyzer)sender).FindLeafNodes();
                foreach (ContextNode node in nodes)
                {
                    if (node is InkWordNode)
                    {
                        InkWordNode t = node as InkWordNode;
                        Rect l = t.Location.GetBounds();
                        System.Windows.Point a = new System.Windows.Point(l.Width + l.Width, l.Height + l.Height);
                        double de = l.Height;
                        Brush be = Brushes.Blue;

                        //switch (t.InkRecognitionConfidence)
                        //{
                        //    case InkRecognitionConfidence.Intermediate:
                        //        be = Brushes.Green;
                        //        break;
                        //    case InkRecognitionConfidence.Poor:
                        //        be = Brushes.Red;
                        //        break;
                        //    case InkRecognitionConfidence.Unknown:
                        //        be = Brushes.Brown;
                        //        break;
                        //}


                        GistaFigure figure = new GistaFigure(t.GetRecognizedString(), a, de, be);
                        //ink.Children.Add(figure);
                       
                        textBox1.Text = figure.ft.Text;
                        try
                        {
                            lblw1.Content = figure.ft.Text.ElementAt(0);
                            lblw2.Content = figure.ft.Text.ElementAt(1);
                            lblw3.Content = figure.ft.Text.ElementAt(2);
                        }
                        catch (Exception ex)
                        { }
                        

                    }
                    //else if (node is InkDrawingNode)
                    //{
                    //    InkDrawingNode d = node as InkDrawingNode;
                    //    GistaFigure figure = new GistaFigure(d.GetShapeName(), d.Centroid, Brushes.Red);
                    //    Shape shape = d.GetShape();
                    //    if (shape != null)
                    //    {
                    //        shape.Stroke = Brushes.Blue;
                    //        shape.StrokeThickness = 2;
                    //        myInkCanvas.Children.Add(shape);
                    //    }
                    //    myInkCanvas.Children.Add(figure);
                    //}

                }
            }
        }

        bool closing = false;
        const int skeletonCount = 6;
        Skeleton[] allSkeletons = new Skeleton[skeletonCount];

        void kinectSensorChooser1_KinectSensorChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            KinectSensor old = (KinectSensor)e.OldValue;

            StopKinect(old);

            KinectSensor sensor = (KinectSensor)e.NewValue;

            if (sensor == null)
            {
                return;
            }


            var parameters = new TransformSmoothParameters
            {
                Smoothing = 0.1f,
                Correction = 0.0f,
                Prediction = 0.0f,
                JitterRadius = 0.1f,
                MaxDeviationRadius = 0.5f
            };
            sensor.SkeletonStream.Enable(parameters);

            sensor.SkeletonStream.Enable();

            sensor.AllFramesReady += new EventHandler<AllFramesReadyEventArgs>(sensor_AllFramesReady);
            sensor.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30);
            sensor.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30);

            try
            {
                sensor.Start();
            }
            catch (System.IO.IOException)
            {
                kinectSensorChooser1.AppConflictOccurred();
            }
        }

        void sensor_AllFramesReady(object sender, AllFramesReadyEventArgs e)
        {
            if (closing)
            {
                return;
            }

            //Get a skeleton
            Skeleton first = GetFirstSkeleton(e);

            if (first == null)
            {
                return;
            }

            

            //set scaled position
            //ScalePosition(Head, first.Joints[JointType.Head]);
            //ScalePosition(LeftHand, first.Joints[JointType.HandLeft]);
           // ScalePosition(image2, first.Joints[JointType.HandRight]);
            GetCameraPoint(first, e);

            ProcessGesture(first.Joints[JointType.WristRight], first.Joints[JointType.ElbowRight], first.Joints[JointType.HandRight], first.Joints[JointType.ShoulderRight]);

            //Joint ScaledJoint = first.Joints[JointType.HandRight].ScaleTo(990, 600);


        }

        private void ProcessGesture(Joint wristright, Joint elbowright, Joint handright, Joint shoulderright)
        {

            SkeletonPoint vector = new SkeletonPoint();
            vector.X = ScaleVector(1350, handright.Position.X);
            vector.Y = ScaleVector(950, -handright.Position.Y);
            vector.Z = handright.Position.Z;

            handright.Position = vector;

            int topofscreen;
            int leftofscreen;

            leftofscreen = Convert.ToInt32(handright.Position.X);
            topofscreen = Convert.ToInt32(handright.Position.Y);

            SetCursorPos(leftofscreen, topofscreen);

            Thread.Sleep(1);

            Vector3D a1 = new Vector3D(elbowright.Position.X, elbowright.Position.Y, elbowright.Position.Z);
            a1.Normalize();
            Vector3D a2 = new Vector3D(shoulderright.Position.X, shoulderright.Position.Y, shoulderright.Position.Z);
            a2.Normalize();
            Vector3D a3 = new Vector3D(wristright.Position.X, wristright.Position.Y, wristright.Position.Z);
            a3.Normalize();
            Vector3D b1 = a3 - a1;
            Vector3D b2 = a2 - a1;
            double abt = Vector3D.AngleBetween(b1, b2);

            //float abtv = AngleBetweenTwoVectors(b1, b2);
            
            //lblScore.Content = abt;
            //ex.Content = elbowright.Position.X;
            //ey.Content = elbowright.Position.Y;
            //ez.Content = elbowright.Position.Z;
            
            //wx.Content = wristright.Position.X;
            //wy.Content = wristright.Position.Y;
            //wz.Content = wristright.Position.Z;

            //sx.Content = shoulderright.Position.X;
            //sy.Content = shoulderright.Position.Y;
            //sz.Content = shoulderright.Position.Z;


            //if (abt < 180 && abt > 95)
            if(rightDepthPoint.Depth > 1200 && rightDepthPoint.Depth < 1400)
            {
                //mouse_event(MOUSEEVENTF_LEFTUP, leftofscreen, topofscreen, 0, 0);
                mouse_event(MOUSEEVENTF_LEFTDOWN, leftofscreen, topofscreen, 0, 0);
                //if( )
                //{
                //    mouse_event(MOUSEEVENTF_LEFTUP, leftofscreen, topofscreen, 0, 0);
                //}
            }
             else
            {
                mouse_event(MOUSEEVENTF_LEFTUP, leftofscreen, topofscreen, 0, 0);
            }
           

        }



        //private void ProcessGesture(Joint wristright, Joint elbowright, Joint handright, Joint shoulderright)
        //{

        //    SkeletonPoint vector = new SkeletonPoint();
        //    vector.X = ScaleVector(1350, handright.Position.X);
        //    vector.Y = ScaleVector(950, -handright.Position.Y);
        //    vector.Z = handright.Position.Z;

        //    handright.Position = vector;

        //    int topofscreen;
        //    int leftofscreen;

        //    leftofscreen = Convert.ToInt32(handright.Position.X);
        //    topofscreen = Convert.ToInt32(handright.Position.Y);

        //    SetCursorPos(leftofscreen, topofscreen);

        //    Thread.Sleep(1);

        //    Vector3D a1 = new Vector3D(elbowright.Position.X, elbowright.Position.Y, elbowright.Position.Z);
        //    a1.Normalize();
        //    Vector3D a2 = new Vector3D(shoulderright.Position.X, shoulderright.Position.Y, shoulderright.Position.Z);
        //    a2.Normalize();
        //    Vector3D a3 = new Vector3D(wristright.Position.X, wristright.Position.Y, wristright.Position.Z);
        //    a3.Normalize();
        //    Vector3D b1 = a3 - a1;
        //    Vector3D b2 = a2 - a1;
        //    double abt = Vector3D.AngleBetween(b1, b2);
        //    //float abtv = AngleBetweenTwoVectors(b1, b2);

        //    lblScore.Content = abt;

        //    if (abt < 180 && abt > 95)
        //    {
                

        //        mouse_event(MOUSEEVENTF_LEFTUP, leftofscreen, topofscreen, 0, 0);

        //        mouse_event(MOUSEEVENTF_LEFTDOWN, leftofscreen, topofscreen, 0, 0);
        //    }

        //    else
        //    {
        //        mouse_event(MOUSEEVENTF_LEFTUP, leftofscreen, topofscreen, 0, 0);
        //        mouse_event(MOUSEEVENTF_LEFTUP, leftofscreen, topofscreen, 0, 0);
        //    }

        //}

        public float AngleBetweenTwoVectors(Vector3 vectorA, Vector3 vectorB)
        {
            float dotProduct = 0.0f;
            dotProduct = Vector3.Dot(vectorA, vectorB);

            return (float)Math.Acos(dotProduct);
        }


        private float ScaleVector(int length, float position)
        {
            float value = (((((float)length) / 1f) / 2f) * position) + (length / 2);
            if (value > length)
            {
                return (float)length;
            }
            if (value < 0f)
            {
                return 0f;
            }
            return value;
        }

        void GetCameraPoint(Skeleton first, AllFramesReadyEventArgs e)
        {

            using (DepthImageFrame depth = e.OpenDepthImageFrame())
            {
                if (depth == null ||
                    kinectSensorChooser1.Kinect == null)
                {
                    return;
                }


                //Map a joint location to a point on the depth map
                //head
                //DepthImagePoint headDepthPoint =
                //    depth.MapFromSkeletonPoint(first.Joints[JointType.Head].Position);
                //left hand
                //DepthImagePoint leftDepthPoint =
                //    depth.MapFromSkeletonPoint(first.Joints[JointType.HandLeft].Position);
                //right hand
                //DepthImagePoint 
                    rightDepthPoint =
                    depth.MapFromSkeletonPoint(first.Joints[JointType.HandRight].Position);
                    lblScore.Content = rightDepthPoint.Depth;
                

                //Map a depth point to a point on the color image
                //head
                //ColorImagePoint headColorPoint =
                //    depth.MapToColorImagePoint(headDepthPoint.X, headDepthPoint.Y,
                //    ColorImageFormat.RgbResolution640x480Fps30);
                ////left hand
                //ColorImagePoint leftColorPoint =
                //    depth.MapToColorImagePoint(leftDepthPoint.X, leftDepthPoint.Y,
                //    ColorImageFormat.RgbResolution640x480Fps30);
                //right hand
                //ColorImagePoint rightColorPoint =
                //    depth.MapToColorImagePoint(rightDepthPoint.X, rightDepthPoint.Y,
                //    ColorImageFormat.RgbResolution640x480Fps30);


                //Set location
                //CameraPosition(Head, headColorPoint);
                //CameraPosition(LeftHand, leftColorPoint);
                //CameraPosition(RightHand, rightColorPoint);

            }
        }


        Skeleton GetFirstSkeleton(AllFramesReadyEventArgs e)
        {
            using (SkeletonFrame skeletonFrameData = e.OpenSkeletonFrame())
            {
                if (skeletonFrameData == null)
                {
                    return null;
                }


                skeletonFrameData.CopySkeletonDataTo(allSkeletons);

                //get the first tracked skeleton
                //Skeleton first = (from s in allSkeletons
                //                  where s.TrackingState == SkeletonTrackingState.Tracked
                //                  select s).FirstOrDefault();

                Skeleton first = null;

                foreach (Skeleton s in allSkeletons)
                {
                    if (s.TrackingState == SkeletonTrackingState.Tracked)
                    {
                        if (first == null)
                        {
                            first = s;
                        }
                        else
                        {
                            if (first.Position.Z > s.Position.Z)
                            {
                                first = s;
                            }

                        }

                    }

                }

                return first;
            }
        }

        
        private void StopKinect(KinectSensor sensor)
        {
            if (sensor != null)
            {
                if (sensor.IsRunning)
                {
                    //stop sensor 
                    sensor.Stop();

                    //stop audio if not null
                    if (sensor.AudioSource != null)
                    {
                        sensor.AudioSource.Stop();
                    }


                }
            }
        }

        private void CameraPosition(FrameworkElement element, ColorImagePoint point)
        {
            //Divide by 2 for width and height so point is right in the middle 
            // instead of in top/left corner
            Canvas.SetLeft(element, point.X - element.Width / 2);
            Canvas.SetTop(element, point.Y - element.Height / 2);

        }


        private void ScalePosition(FrameworkElement element, Joint joint)
        {
            //convert the value to X/Y
            //Joint scaledJoint = joint.ScaleTo(1280, 720); 

            //convert & scale (.3 = means 1/3 of joint distance)
            Joint scaledJoint = joint.ScaleTo(1280, 720, 1f, 1f);

            Canvas.SetLeft(element, scaledJoint.Position.X);
            Canvas.SetTop(element, scaledJoint.Position.Y);

        }


        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            closing = true;
            StopKinect(kinectSensorChooser1.Kinect);
        }

        //#region custompen
        //public class Window2Panel : Panel
        //{
        //    private VisualCollection _col;

        //    public Window2Panel()
        //    {
        //        _col = new VisualCollection(this);
        //        DynamicRenderer dr = new DynamicRenderer();
        //        _col.Add(dr.RootVisual);
        //        this.StylusPlugIns.Add(dr);
        //    }

        //    protected override Visual GetVisualChild(int index)
        //    {
        //        return _col[index];
        //    }

        //    protected override int VisualChildrenCount
        //    {
        //        get
        //        {
        //            return _col.Count;
        //        }
        //    }

        //    bool down = false;


        //    protected override void OnMouseDown(MouseButtonEventArgs e)
        //    {
        //        down = true;
        //        pen = new CustomPen(e.GetPosition(this));

        //    }

        //    protected override void OnMouseMove(MouseEventArgs e)
        //    {
        //        if (down && pen != null)
        //        {
        //            pen.AddPoint(e.GetPosition(this));
        //        }
        //    }
        //    protected override void OnMouseUp(MouseButtonEventArgs e)
        //    {
        //        down = false;
        //        try
        //        {
        //            if (pen != null)
        //            {
        //                pen.Draw();
        //                _col.Add(pen);
        //            }
        //        }
        //        catch (Exception ex)
        //        {
        //        }
        //    }
        //}

        //public class CustomPen : DrawingVisual
        //{
        //    public Stroke stroke;

        //    public CustomPen(System.Windows.Point point)
        //        : this(new StylusPoint(point.X, point.Y))
        //    {
        //    }

        //    public CustomPen(StylusPoint point)
        //    {
        //        StylusPointCollection points = new StylusPointCollection();
        //        points.Add(point);
        //        stroke = new Stroke(points);
        //        stroke.DrawingAttributes.Height = 20;
        //        stroke.DrawingAttributes.Width = 20;
        //        stroke.DrawingAttributes.Color = Colors.White;


        //    }

        //    public void AddPoint(System.Windows.Point point)
        //    {
        //        this.AddPoint(new StylusPoint(point.X, point.Y));
        //    }

        //    public void AddPoint(StylusPoint point)
        //    {
        //        stroke.StylusPoints.Add(point);
        //    }

        //    public void Draw()
        //    {
        //        DrawingContext dc = this.RenderOpen();
        //        stroke.Draw(dc);
        //        dc.Close();
        //    }
        //}
        //#endregion

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            ink.Strokes.Clear();
            onLoaded(sender, e);
            textBox1.Clear();
        }

        private void button2_Click(object sender, RoutedEventArgs e)
        {
            m_analyzer.BackgroundAnalyze();
        }

        private void Window_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.F2)
            {
                m_analyzer.BackgroundAnalyze();
                Thread.Sleep(1000);
                CheckWriting();
            }

            if (e.Key == Key.F3)
            {
                var d = new MainGame();
                this.Hide();
                d.Show();
            }

        }

        private void CheckWriting()
        {
            if (textBox1.Text != wording && wording.ElementAt(2) != null)
            {
                
                ink.Strokes.Clear();

                Image img1 = new Image();
                Image img2 = new Image();
                Image img3 = new Image();
                img1.Source = new BitmapImage(new Uri("/letters/" + wording.ElementAt(0) + ".png", UriKind.RelativeOrAbsolute));
                img2.Source = new BitmapImage(new Uri("/letters/" + wording.ElementAt(1) + ".png", UriKind.RelativeOrAbsolute));
                img3.Source = new BitmapImage(new Uri("/letters/" + wording.ElementAt(2) + ".png", UriKind.RelativeOrAbsolute));

                InkCanvas.SetTop(img1, 20);
                InkCanvas.SetLeft(img1, 20);
                ink.Children.Add(img1);
                
                InkCanvas.SetTop(img2, 20);
                InkCanvas.SetLeft(img2, 140);
                ink.Children.Add(img2);
                
                InkCanvas.SetTop(img3, 20);
                InkCanvas.SetLeft(img3, 260);
                ink.Children.Add(img3);
            }
        }

    }
}
